<?php

namespace App\Modules\Apicrzs\Services\WeChat;

use App\Exceptions\Exception;
use App\Library\Wechat\WeChatApi;
use App\Modules\Apicrzs\Entities\UsersModel;
use App\Modules\Apicrzs\Services\BaseServices;

use App\Traits\CryptAES;
use Darabonba\GatewaySpi\Models\InterceptorContext\response;
use EasyWeChat\MiniApp\Application;
//use EasyWeChat\OfficialAccount\Application as OAApplication;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use function MongoDB\BSON\toCanonicalExtendedJSON;

class RoutineServices extends BaseServices
{
    public function __construct(UsersModel $model)
    {
        $this->model = $model;
    }

    /**
     * 静默登录，获取微信用户openid，后续与用户表绑定，并生成token。
     * @param $code
     * @return array|void
     * @throws Exception
     */
    public function silenceAuth($params)
    {
        $code = $params['code'];
        $spread_code = $params['spread_code'] ?? '';
        $spread_spid = $params['spread_spid'] ?? "";

        $wxconfig =  getWxConfig('MiniApp');
        //完整参数
        $param=array();
        $param[]='appid='.$wxconfig['app_id'];
        $param[]='secret='.$wxconfig['secret'];
        $param[]='js_code='.$code;
        $param[]='grant_type=authorization_code';
        $params=implode('&',$param);    //用&符号连起来
        $url ="https://api.weixin.qq.com/sns/jscode2session".'?'.$params;
        //请求接口
        $client = new \GuzzleHttp\Client([
            'timeout' => 60
        ]);
        $res = $client->request('GET',$url);
        //openid和session_key
        $result = json_decode($res->getBody()->getContents(),true);

        /* exit(json_encode($data));

         $code = request('code');
         $access_token = WeChatApi::getAccessToken($code);
         Log::info($code);
         // 创建微信小程序对象
         $app = new Application(getWxConfig('MiniApp'));
         $utils = $app->getUtils();

         $result = $utils->codeToSession($code);*/

        // $result = $wechat->getUtils()->codeToSession($code);
        if (!isset($result['openid'])) {
            $this->error = '请求错误';
            return false;
        }
        $openid = $result['openid'];
        $unionid = $result['unionid']??"";
        $session_key = $result['session_key'];

        $user_info = $this->model->where('openid', $openid)->first();
        xdebug($user_info,'静默登录-api','user/silenceAuth');
        $spread_code = generateInvitationCode();
        $bindPhone = false;
        if ($user_info) {
            if (!$user_info['mobile'] == '') {
                $bindPhone = true;
            }
            if ($user_info['unionid'] == '') {
                $this->update(['id'=>$user_info['id'],'unionid'=>$unionid]);
            }
            if (!$user_info['spread_code']){
                $spread_code = $user_info['id'].generateInvitationCode();
                $this->update(['id'=>$user_info['id'],'spread_code'=>$spread_code]);
            }

        } else {
            $salt = rand_str();
            $insert_array['openid'] = $openid;
            $insert_array['unionid'] = $unionid;
            $insert_array['salt'] = $salt;
            $insert_array['water_role'] = "intake";
            $insert_array['water_intake'] = 0;
            $insert_array['water_manage'] = 0;
            $insert_array['water_buy'] = 0;
            $insert_array['last_time'] = time();
            $insert_array['last_ip'] = get_ip();
        }

        $routineInfo['openid'] = $openid;
        $routineInfo['unionid'] = $unionid;
        $routineInfo['spid'] = $spread_spid;
        $routineInfo['code'] = $spread_code;
        $routineInfo['session_key'] = $result['session_key'] ?? "";
        $createData = $routineInfo;
        $userInfoKey = md5($openid . '_' . time() . '_routine');


        DB::beginTransaction();
        try {
            if (!$user_info) {
                $this->detail = parent::create($insert_array); // TODO: Change the autogenerated stub
                $this->detail->usersIdCard()->create(['user_id'=>$this->detail['id']]);
                $user_info = $this->detail;
                xdebug($this->detail,'静默登录-api- 新增用户','user/silenceAuth');
            }
            $token = CryptAES::createToken([
                'user_id' => $user_info['id'],
                'mobile' => $user_info['mobile'],
                'water_role' => $user_info['water_role'],
                'salt' => rand_str(),
            ], 'user_grzq');
            Cache::set($userInfoKey, $createData);
            DB::commit();
            return [
                'bindPhone' => $bindPhone,
                'openid' => $openid,
                'session_key' => $session_key,
                'access_token' => $token,
                'user_info' => $user_info,
                'access_token_key' => $userInfoKey
            ];
        } catch (Exception $e) {
            DB::rollBack();
            $this->error = '请求失败';
            return false;
        }
    }

    public function authLogin($params)
    {
        $code = $params['code'];

        $spread_code = $params['spread_code'] ?? '';
        $spread_spid = $params['spread_spid'] ?? "";
        // 创建微信小程序对象
        $wechat = new Application(getWxConfig('MiniApp'));
        $result = $wechat->getUtils()->codeToSession($code);

        if (!isset($result['openid'])) {
            $this->error = '请求错误';
            return false;
        }
        $openid = $result['openid'];

        $user_info = $this->model->where('openid', $openid)->first();
        xdebug($user_info,'静默登录-api- 新增用户','user/authLogin');
        $bindPhone = false;
        if ($user_info) {
            if (!$user_info['mobile'] == '') {
                $bindPhone = true;
            }
        } else {

            $salt = rand_str();
            $insert_array['openid'] = $openid;
            $insert_array['salt'] = $salt;
            $insert_array['water_role'] = "intake";
            $insert_array['water_intake'] = 0;
            $insert_array['water_manage'] = 0;
            $insert_array['water_buy'] = 0;
            $insert_array['last_time'] = time();
            $insert_array['last_ip'] = get_ip();
        }

        $routineInfo['openid'] = $openid;
        $routineInfo['spid'] = $spread_spid;
        $routineInfo['code'] = $spread_code;
        $routineInfo['session_key'] = $result['session_key'] ?? "";
        $createData = $routineInfo;
        $userInfoKey = md5($openid . '_' . time() . '_routine');


        DB::beginTransaction();
        try {
            if (!$user_info) {
                $this->detail = parent::create($insert_array); // TODO: Change the autogenerated stub
                $user_info = $this->detail;
            }else{
                $insert_array['id'] = $user_info['id'];
                $this->detail = parent::update($insert_array);
            }
            $token = CryptAES::createToken([
                'user_id' => $user_info['id'],
                'mobile' => $user_info['mobile'],
                'water_role' => $user_info['water_role'],
                'salt' => rand_str(),
            ], 'user_grzq');
            Cache::set($userInfoKey, $createData);
            DB::commit();

            return ['bindPhone' => $bindPhone, 'openid' => $openid, 'access_token' => $token,
                'user_info' => $user_info, 'access_token_key' => $userInfoKey];
        } catch (Exception $e) {
            DB::rollBack();
            $this->error = '请求失败';
            return false;
        }
    }

    public function getXcxUserInfo($code)
    {

        $wechat = Config::get('wechat')['MiniApp'];
        if (!$code) return array();    // 小程序专用信息
        $appid = $wechat['app_id']; // 南泥湾商户版
        $appsecret = $wechat['secret'];
        $url = "https://api.weixin.qq.com/sns/jscode2session?appid={$appid}&secret={$appsecret}&js_code={$code}&grant_type=authorization_code";

        $res = $this->http_request($url);

        return $res;
    }

    /** * curl模拟http请求GET/POST * @param $url * @param null $data * @return array */
    public function http_request($url, $data = null)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        // 以文件流形式返回
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        if (!empty($data)) {
            // POST请求
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        }
        $output = curl_exec($ch);
        curl_close($ch);
        // 返回数组
        return json_decode($output, true);
    }

    public function authType($params)
    {
        $code = $params['code'];
        $iv = $params['iv'];
        $sessionKey = $params['key'];
        $encryptedData = $params['encryptedData'];
        if (!$code || !$iv || !$encryptedData) {
            $this->error = "参数错误";
            return false;
        }
        $spread_code = $params['spread_code'] ?? '';
        $spread_spid = $params['spread_spid'] ?? '';

        $app = new Application(getWxConfig('MiniApp'));
        $utils = $app->getUtils();
        $response = $utils->codeToSession($code);
        $session = $utils->decryptSession($sessionKey, $iv, $encryptedData);

        return [$response, $session];
    }

    /**
     * 绑定手机号
     * @param $params
     * @return array|false
     * @throws Exception
     */
    public function authBindingPhone($params)
    {
        $code = $params['code'];
        $iv = $params['iv'];
        $openid = $params['openid'];
        xdebug($openid,'绑定手机号-api- $openid','user/authBindingPhone');
        $sessionKey = $params['key'];
        $tokenKey = $params['access_token_key'];
        $encryptedData = $params['encryptedData'];
        $spread_code = $params['spread_code'] ?? '';
        $spread_spid = $params['spread_spid'] ?? '';
        $nickname = $params['nickname'] ?? '甄泉';
        $user_key = Cache::get($tokenKey);
        Cache::delete($tokenKey);

        if (!$user_key) {
            $this->error = '请重新加载...';
            return false;
        }
        if (!$code || !$iv || !$encryptedData) {
            $this->error = "参数错误";
            return false;
        }

        $wechat = new Application(getWxConfig('MiniApp'));
        $utils = $wechat->getUtils();
        $result = $utils->decryptSession($sessionKey, $iv, $encryptedData);
        $phoneNumber = $result['phoneNumber'];
        xdebug($phoneNumber,'绑定手机号-api- 手机号','user/authBindingPhone');
        $user_info_mobile = $this->model->where(['mobile' => $phoneNumber])->first();
        $user_update['last_time'] = time();
        $user_update['last_ip'] = get_ip();
        $spread_code = $user_info_mobile['id'].generateInvitationCode();
        if (!$user_info_mobile) {
            $user_info_openid = $this->model->where(['openid' => $openid])->first();
            $user_update['id'] = $user_info_openid['id'];
            $user_update['nickname'] = $user_info_openid['nickname']??$nickname;
            $user_update['username'] = $phoneNumber;
            $user_update['mobile'] = $phoneNumber;
            if (!$user_info_openid['spread_code']){
                $user_update['spread_code'] = $spread_code;
            }
        } else {
            $user_update['id'] = $user_info_mobile['id'];
            $user_update['openid'] = $openid;
            $user_update['spread_code'] = $spread_code;
        }

        $this->update($user_update);

        $user_info = $this->model->where(['openid'=>$openid])->first();

        $routineInfo['user_id'] = $user_info['id'];
        $routineInfo['water_role'] = $user_info['water_role'];
        $routineInfo['mobile'] = $user_info['mobile'];
        $routineInfo['openid'] = $openid;
        $routineInfo['spid'] = $spread_spid;
        $routineInfo['code'] = $spread_code;
        $createData = $routineInfo;
        xdebug($routineInfo,'绑定手机号-api- 修改','user/authBindingPhone');

        $userInfoKey = md5($openid . '_' . time() . '_routine');
        $token = CryptAES::createToken([
            'user_id' => $user_info['id'],
            'mobile' => $phoneNumber,
            'water_role' => $user_info['water_role'],
            'salt' => rand_str(),
        ], 'user_grzq');
        Cache::set($userInfoKey, $createData);

        return ["routineInfo" => $routineInfo,
            'user_info' => $user_info, 'access_token' => $token, 'access_token_key' => $userInfoKey];
    }



}
